package com.xinsoft.service.impl;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xinsoft.common.exception.BDException;
import com.xinsoft.entity.dto.ExcelErrRowDTO;
import com.xinsoft.entity.dto.SysSupplierDTO;
import com.xinsoft.entity.dto.SysSupplierPageParam;
import com.xinsoft.entity.po.*;
import com.xinsoft.entity.vo.SysSupplierVo;
import com.xinsoft.mapper.SysSupplierMapper;
import com.xinsoft.service.*;
import com.xinsoft.utils.ExcelUtils;
import com.xinsoft.utils.TokenUtil;
import com.xinsoft.validator.ValidatorUtils;
import org.apache.commons.lang.StringUtils;
import org.json.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
* @author hsm
* @description 针对表【sys_supplier(供应商)】的数据库操作Service实现
* @createDate 2023-05-22 15:13:03
*/
@Service
public class SysSupplierServiceImpl extends ServiceImpl<SysSupplierMapper, SysSupplier>
    implements SysSupplierService{

    @Resource
    private SysSupplierLinkmanService sysSupplierLinkmanService;

    @Resource
    private SysUserService sysUserService;

    @Resource
    private SysDictionaryService sysDictionaryService;

    @Resource
    private SysFileHisService sysFileHisService;

    @Resource
    private SysDeptService sysDeptService;


    @Override
    public SysSupplier addSysSupplier(SysSupplierDTO sysSupplierDTO) {


        // 判断供应商名称是否重复
        QueryWrapper<SysSupplier> sysSupplierQuery = new QueryWrapper<>();
        sysSupplierQuery.select("id");
        sysSupplierQuery.eq("supplier_name",sysSupplierDTO.getSupplierName());
        List suppliers = this.list(sysSupplierQuery);

        if(CollectionUtil.isNotEmpty(suppliers)){
            throw new BDException("操作失败，供应商名称重复！");
        }

        //判断供应商code是否重复
        QueryWrapper<SysSupplier> sysSupplierQueryByCode = new QueryWrapper<>();
        sysSupplierQueryByCode.select("id");
        sysSupplierQueryByCode.eq("supplier_code",sysSupplierDTO.getSupplierCode());
        List suppliers2 = this.list(sysSupplierQueryByCode);
        if(CollectionUtil.isNotEmpty(suppliers2)){
            throw new BDException("操作失败，供应商编号重复！");
        }

        //判断客户社会信用统一码是否重复
        QueryWrapper<SysSupplier> sysSupplierQueryByUscc = new QueryWrapper<>();
        sysSupplierQueryByUscc.select("id");
        sysSupplierQueryByUscc.eq("uscc",sysSupplierDTO.getUscc());
        List suppliers3 = this.list(sysSupplierQueryByUscc);
        if(CollectionUtil.isNotEmpty(suppliers3)){
            throw new BDException("操作失败，供应商社会统一信用代码重复！");
        }

        SysSupplier supplier = new SysSupplier();
        BeanUtils.copyProperties(sysSupplierDTO,supplier);
        supplier.setAuditStatus(0);//未审核
        this.save(supplier);

        //按照之前表设计将联系人保存在supplierLinkman表中
        if(CollectionUtil.isNotEmpty(sysSupplierDTO.getSysSupplierLinkmanList())){
            for (SysSupplierLinkman sysSupplierLinkman : sysSupplierDTO.getSysSupplierLinkmanList()) {
                sysSupplierLinkman.setSupplierId(supplier.getId());
            }
            sysSupplierLinkmanService.saveBatch(sysSupplierDTO.getSysSupplierLinkmanList());//保存联系人
        }

        return supplier;

    }

    @Override
    public SysSupplier editSysSupplier(SysSupplierDTO sysSupplierDTO) {

        //判断是否可以修改//禁用状态且未审核
        SysSupplier supplier = this.getById(sysSupplierDTO.getId());
        if(Objects.equals(supplier.getAuditStatus(),1)){
            throw new BDException("操作失败，供应商已审核无法修改！");
        }

        // 判断供应商名称是否重复
        QueryWrapper<SysSupplier> sysSupplierQuery = new QueryWrapper<>();
        sysSupplierQuery.select("id");
        sysSupplierQuery.eq("supplier_name",sysSupplierDTO.getSupplierName());
        sysSupplierQuery.ne("id",sysSupplierDTO.getId());
        List suppliers = this.list(sysSupplierQuery);

        if(CollectionUtil.isNotEmpty(suppliers)){
            throw new BDException("操作失败，供应商名称重复！");
        }

        //判断客户社会信用统一码是否重复
        QueryWrapper<SysSupplier> sysSupplierQueryByUscc = new QueryWrapper<>();
        sysSupplierQueryByUscc.select("id");
        sysSupplierQueryByUscc.eq("uscc",sysSupplierDTO.getUscc());
        sysSupplierQueryByUscc.ne("id",sysSupplierDTO.getId());
        List suppliers3 = this.list(sysSupplierQueryByUscc);
        if(CollectionUtil.isNotEmpty(suppliers3)){
            throw new BDException("操作失败，供应商社会统一信用代码重复！");
        }

        BeanUtils.copyProperties(sysSupplierDTO,supplier);
        supplier.setId(sysSupplierDTO.getId());
        supplier.setSupplierCode(null);
        supplier.setAuditStatus(0);//未审核
        // 保存供应商
        this.updateById(supplier);

        //按照之前表设计将联系人保存在supplierLinkman表中
        //移除之前的数据
        QueryWrapper linkManQuery = new QueryWrapper();
        linkManQuery.eq("do_delete",0);
        linkManQuery.eq("supplier_id",supplier.getId());
        sysSupplierLinkmanService.remove(linkManQuery);
        // 保存联系人
        if(CollectionUtil.isNotEmpty(sysSupplierDTO.getSysSupplierLinkmanList())){
            for (SysSupplierLinkman sysSupplierLinkman : sysSupplierDTO.getSysSupplierLinkmanList()) {
                sysSupplierLinkman.setSupplierId(supplier.getId());
            }
            sysSupplierLinkmanService.saveBatch(sysSupplierDTO.getSysSupplierLinkmanList());//保存联系人
        }
        return supplier;
    }

    @Override
    public void del(List<Integer> ids) {
        QueryWrapper<SysSupplier> sysUserQuery1 = new QueryWrapper<>();
        sysUserQuery1.eq("supplier_status",1);//启用
        sysUserQuery1.in("id",ids);//启用
        List<SysSupplier> suppliers = this.list(sysUserQuery1);
        //判断是否已启用
        if(CollectionUtil.isNotEmpty(suppliers)){
            throw new BDException("操作失败，"+suppliers.get(0).getSupplierName()+"已启用无法删除！");
        }

        QueryWrapper<SysSupplier> sysUserQuery2 = new QueryWrapper<>();
        sysUserQuery2.eq("audit_status",1);//启用
        List<SysSupplier> suppliers2 = this.list(sysUserQuery2);
        //判断是否已启用
        if(CollectionUtil.isNotEmpty(suppliers)){
            throw new BDException("操作失败，"+suppliers2.get(0).getSupplierName()+"已审核无法删除！");
        }

        // 删除
        removeByIds(ids);

        // 删除联系人
        QueryWrapper userRoleQuery = new QueryWrapper();
        userRoleQuery.in("supplier_id",ids);
        sysSupplierLinkmanService.remove(userRoleQuery);
    }

    @Override
    public SysSupplierDTO getSysSupplier(Integer id) {
        SysSupplier supplier = this.getById(id);
        SysSupplierDTO supplierDTO = new SysSupplierDTO();
        BeanUtils.copyProperties(supplier,supplierDTO);
        supplierDTO.setId(supplier.getId());
        //获取创建人名称
        SysUser create = sysUserService.getById(supplier.getCreateBy());
        if(create!=null){
            supplierDTO.setCreateByName(create.getRealName());
        }
        //获取业务员名称
        SysUser belongUser = sysUserService.getById(supplier.getBelongUserId());
        if(belongUser!=null){
            supplierDTO.setBelongUserName(belongUser.getRealName());
            //获取业务员部门名称
            SysDept dept = sysDeptService.getById(belongUser.getDeptId());
            if(dept!=null){
                supplierDTO.setBelongDeptName(dept.getDeptName());
            }
        }

        //获取类型名称
        SysDictionary dictionary = sysDictionaryService.getById(supplier.getType());
        if(dictionary!=null){
            supplierDTO.setTypeName(dictionary.getTypeName());
        }

        //获取审核人名称
        SysUser audit = sysUserService.getById(supplier.getAuditId());
        if(audit!=null){
            supplierDTO.setAuditName(audit.getRealName());
        }
        //获取联系人list
        QueryWrapper userRoleQuery = new QueryWrapper();
        userRoleQuery.in("supplier_id",supplierDTO.getId());
        supplierDTO.setSysSupplierLinkmanList(sysSupplierLinkmanService.list(userRoleQuery));
        return supplierDTO;
    }

    @Override
    public void enable(List<Integer> ids) {
        UpdateWrapper<SysSupplier> sysUserUpdateQuery = new UpdateWrapper<>();
        sysUserUpdateQuery.set("supplier_status",1);//启用
        sysUserUpdateQuery.in("id",ids);
        sysUserUpdateQuery.eq("do_delete",0);
        this.update(sysUserUpdateQuery);
    }

    @Override
    public void disable(List<Integer> ids) {
        UpdateWrapper<SysSupplier> sysUserUpdateQuery = new UpdateWrapper<>();
        sysUserUpdateQuery.set("supplier_status",0);//禁用
        sysUserUpdateQuery.in("id",ids);
        sysUserUpdateQuery.eq("do_delete",0);
        this.update(sysUserUpdateQuery);
    }

    @Override
    public void audit(List<Integer> ids) {
        UpdateWrapper<SysSupplier> sysUserUpdateQuery = new UpdateWrapper<>();
        sysUserUpdateQuery.set("audit_status",1);//审核
        sysUserUpdateQuery.set("audit_id", TokenUtil.getUserId());//设置审核人
        sysUserUpdateQuery.in("id",ids);
        sysUserUpdateQuery.eq("do_delete",0);
        this.update(sysUserUpdateQuery);
    }

    @Override
    public void deAudit(List<Integer> ids) {
        UpdateWrapper<SysSupplier> sysUserUpdateQuery = new UpdateWrapper<>();
        sysUserUpdateQuery.set("audit_status",0);//反审核
        sysUserUpdateQuery.set("audit_id", TokenUtil.getUserId());//设置审核人
        sysUserUpdateQuery.in("id",ids);
        sysUserUpdateQuery.eq("do_delete",0);
        this.update(sysUserUpdateQuery);

    }

    @Override
    public JSONObject importExcel(MultipartFile multipartFile, HttpServletResponse response) throws IOException {
        // 初始化错误行信息list，用来记录导入失败的rowNum
        List<ExcelErrRowDTO> errRowDOs = new ArrayList<>();

        // 对excel是否为空进行check
        if (multipartFile.isEmpty()) {
            throw new BDException("导入失败，请选择文件！");
        }

        //设置excel参数
        ImportParams params = new ImportParams();
        params.setTitleRows(1);
        params.setHeadRows(1);
        List<SysSupplierDTO> sysSupplierList;
        List<SysSupplier> sysSuppliers = CollectionUtil.newArrayList();

        JSONObject result = new JSONObject();

        // 解析excel中的行，放到sysSupplierList中
        try {
            // 解析excel
            sysSupplierList = ExcelImportUtil.importExcel(multipartFile.getInputStream(), SysSupplierDTO.class, params);
        } catch (Exception e) {
            throw new BDException("导入失败，文件内容解析错误！");
        }

        //校验
        if (sysSupplierList.size() > 0) {
            //取出excel和db中所有重复的name
            List<String> excelSupplierNames = sysSupplierList.stream()
                    .map(SysSupplierDTO::getSupplierName)
                    .collect(Collectors.toList()); // 获取excel中所有的username
            List<String> dbSupplierNames = this.getAllSupplierName();//获取系统中所有的SupplierName
            List<String> duplicateSupplierNames = new ArrayList<>(); // 存放存在重复的supplierName，用于定位重复存放存在重复的supplierName的行

            if (dbSupplierNames.size() > 0 && excelSupplierNames.size() > 0) {
                dbSupplierNames.addAll(excelSupplierNames);//合并
                duplicateSupplierNames = ExcelUtils.getDuplicateElements(dbSupplierNames);//取出存在重复的username
            }

            //取出excel和db中所有重复的code
            List<String> excelSupplierCodes = sysSupplierList.stream()
                    .map(SysSupplierDTO::getSupplierCode)
                    .collect(Collectors.toList()); // 获取excel中所有的username
            List<String> dbSupplierCodes = this.getAllSupplierCode();//获取系统中所有的Suppliercode
            List<String> duplicateSupplierCodes = new ArrayList<>(); // 存放存在重复的Suppliercode，用于定位重复存放存在重复的supplierName的行

            if (dbSupplierCodes.size() > 0 && excelSupplierCodes.size() > 0) {
                dbSupplierCodes.addAll(excelSupplierCodes);//合并
                duplicateSupplierCodes = ExcelUtils.getDuplicateElements(dbSupplierCodes);//取出存在重复的username
            }

            //取出excel和db中所有重复的uscc
            List<String> excelSupplierUsccs = sysSupplierList.stream()
                    .map(SysSupplierDTO::getUscc)
                    .collect(Collectors.toList()); // 获取excel中所有的username
            List<String> dbSupplierUsccs = this.getAllSupplierUscc();//获取系统中所有的SupplierUscc
            List<String> duplicateSupplierUsccs = new ArrayList<>(); // 存放存在重复的SupplierUscc，用于定位重复存放存在重复的supplierName的行

            if (dbSupplierUsccs.size() > 0 && excelSupplierUsccs.size() > 0) {
                dbSupplierUsccs.addAll(excelSupplierUsccs);//合并
                duplicateSupplierUsccs = ExcelUtils.getDuplicateElements(dbSupplierUsccs);//取出存在重复的username
            }


            // 服务类型(字典 supplier_type)
            List<SysDictionary> dictionaryList =  sysDictionaryService.getDictByTypeCode("supplier_type");
            Map<String, Integer> supplierTypeMap = dictionaryList.stream()
                    .collect(Collectors.toMap(SysDictionary::getDicName, SysDictionary::getId, (v1, v2) -> v2));

            // 人员
            List<SysUser> userList = sysUserService.list();
            Map<String, SysUser> userMap = userList.stream()
                    .collect(Collectors.toMap(SysUser::getRealName, Function.identity(), (v1, v2) -> v2));


            int index = 1;
            for (SysSupplierDTO sysSupplierDTO : sysSupplierList) {
                index ++;
                // check
                StringBuilder stringBuilder = new StringBuilder();
                ExcelErrRowDTO excelErrRowDO= new ExcelErrRowDTO();

                // 参数校验
                stringBuilder.append(ValidatorUtils.validateExcel(sysSupplierDTO));

                // 检验supplierName 是否重复
                if(duplicateSupplierNames.contains(sysSupplierDTO.getSupplierName())){
                    stringBuilder.append("供应商已经存在，请勿重复！");
                }
                // 检验supplierCode 是否重复
                if(duplicateSupplierCodes.contains(sysSupplierDTO.getSupplierCode())){
                    stringBuilder.append("供应商编号已经存在，请勿重复！");
                }

                // 检验supplierUscc 是否重复
                if(duplicateSupplierUsccs.contains(sysSupplierDTO.getUscc())){
                    stringBuilder.append("供应商社会统一信用代码已经存在，请勿重复！");
                }

                // 设置 所属业务员
                if(StringUtils.isNotEmpty(sysSupplierDTO.getBelongUserName())){
                    SysUser user = userMap.get(sysSupplierDTO.getBelongUserName());
                    if(user==null){
                        stringBuilder.append("所属业务员:"+sysSupplierDTO.getBelongUserName()+",在系统中不存在");
                    }else{
                        sysSupplierDTO.setBelongUserId(user.getId());
                        sysSupplierDTO.setBelongDeptId(user.getDeptId());
                    }
                }

                // 服务类型
                if(StringUtils.isNotEmpty(sysSupplierDTO.getTypeName())){
                    Integer typeId = supplierTypeMap.get(sysSupplierDTO.getTypeName());
                    if(typeId==null){
                        stringBuilder.append("服务类型:"+sysSupplierDTO.getTypeName()+",在系统中不存在");
                    }
                    sysSupplierDTO.setType(typeId);
                }

                // 状态 0:禁用，1:正常
                if(StringUtils.equals(sysSupplierDTO.getSupplierStatusName(),"启用")){
                    sysSupplierDTO.setSupplierStatus(1);
                }else{
                    sysSupplierDTO.setSupplierStatus(0);
                }

                // 将错误行信息保存到list
                String errMsg = stringBuilder.toString();
                if(StringUtils.isNotEmpty(errMsg)){
                    excelErrRowDO.setRowIndex(index);
                    excelErrRowDO.setErrMessage(errMsg);
                    errRowDOs.add(excelErrRowDO);
                    continue;
                }
                //保存
                SysSupplier supplier = new SysSupplier();
                BeanUtils.copyProperties(sysSupplierDTO,supplier);
                sysSuppliers.add(supplier);
            }
            saveBatch(sysSuppliers);

            // 导出错误行
            String errFileUrl = ExcelUtils.exportErrRows(errRowDOs,multipartFile,sysFileHisService);
            result.put("errFileUrl",errFileUrl);
        }
        return result;
    }

    @Override
    public List<SysSupplierVo> findListByParam(SysSupplierPageParam param) {
        //不分页
        List<SysSupplierVo> suppliers = this.baseMapper.findListByParam(param);
        //返回值
        return suppliers;
    }

    @Override
    public void insertOrUpdateBatch(List<SysSupplier> sysSupplierList) {
        baseMapper.insertOrUpdateBatch(sysSupplierList);
    }

    @Override
    public IPage<SysSupplierVo> findPageListByParam(SysSupplierPageParam param) {
        //分页
        Page<SysSupplierVo> page = new Page<SysSupplierVo>(param.getCurrentPage(), param.getPageSize());
        //查询分页
        IPage<SysSupplierVo> suppliers = this.baseMapper.findListByParam(page, param);
        //返回值
        return suppliers;
    }

    private List<String> getAllSupplierName() {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.select("supplier_name");
        List<SysSupplier> userList = this.list();
        List<String> usernames = userList.stream().map(SysSupplier::getSupplierName).collect(Collectors.toList());
        return usernames;
    }

    private List<String> getAllSupplierCode() {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.select("supplier_code");
        List<SysSupplier> userList = this.list();
        List<String> codes = userList.stream().map(SysSupplier::getSupplierCode).collect(Collectors.toList());
        return codes;
    }

    private List<String> getAllSupplierUscc() {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.select("uscc");
        List<SysSupplier> userList = this.list();
        List<String> usccs = userList.stream().map(SysSupplier::getUscc).collect(Collectors.toList());
        return usccs;
    }

}




